package com.admin.common.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.admin.common.annotation.Compare;

/**
 * @ClassNameObjectCompare
 * @Description 说明类的作用
 * @Author pangd
 * @Date 2019/11/5 13:36
 * @Version V1.0
 **/
public class ObjectCompare {



    /**
     * 对象比较器
     * 
     * @param oldMap 原对象参数
     * @param newMap 现对象参数
     * @return 返回比较之后的结果
     */
    public static StringBuffer comparatorObject(Map<String, LogValue> oldMap, Map<String, LogValue> newMap) {
        StringBuffer sb = new StringBuffer();
        if (oldMap != null && !oldMap.isEmpty()) {
            Set<Map.Entry<String, LogValue>> comparSet = oldMap.entrySet();
            for (Map.Entry<String, LogValue> entry : comparSet) {
                if (entry == null || newMap.get(entry.getKey()).getValue() == null) {
                    continue;
                }
                LogValue newVo = newMap.get(entry.getKey());
                LogValue oldVo = entry.getValue();
                Object newValue = newVo.getValue();
                Object oldValue = oldVo.getValue();
                Class<?> type = newValue.getClass();
                String typeName = newValue.getClass().getName();
                if (newVo != null) {
                    if ("java.lang.String".equals(typeName)) {
                        String newStr = (String)newValue;
                        String oldStr = (String)oldValue;
                        if (!StringUtils.equals(newStr, oldStr)) {
                            sb.append(showMsg(newVo, newStr, oldStr));
                        }
                    } else if ("java.sql.Timestamp".equals(typeName)) {
                        DateFormat format = new SimpleDateFormat(
                            StringUtils.isBlank(newVo.getFormat()) ? "yyyy-MM-dd HH:mm:ss" : newVo.getFormat());
                        java.sql.Timestamp newTime = (java.sql.Timestamp)newValue;
                        java.sql.Timestamp oldTime = (java.sql.Timestamp)oldValue;
                        String newTempTimeStr = "";
                        String oldTimeTimeStr = "";
                        if (newTime != null) {
                            newTempTimeStr = format.format(newTime);
                        }
                        if (oldTime != null) {
                            oldTimeTimeStr = format.format(oldTime);
                        }
                        if (!StringUtils.equals(newTempTimeStr, oldTimeTimeStr)) {
                            sb.append(showMsg(newVo, format.format(newTime), format.format(oldTime)));
                        }
                    } else if ("java.lang.Long".equals(typeName) || Long.TYPE == type) {
                        java.lang.Long newLog =
                            NumberUtils.createLong(NumberUtils.isCreatable(newValue + "") ? newValue + "" : "0");
                        java.lang.Long oldLog =
                            NumberUtils.createLong(NumberUtils.isCreatable(oldValue + "") ? oldValue + "" : "0");
                        if (newLog.compareTo(oldLog) != 0) {
                            sb.append(showMsg(newVo, newLog, oldLog));
                        }
                    } else if ("java.lang.Integer".equals(typeName) || Integer.TYPE == type) {
                        java.lang.Integer newInt =
                            NumberUtils.createInteger(NumberUtils.isCreatable(newValue + "") ? newValue + "" : "0");
                        java.lang.Integer oldInt =
                            NumberUtils.createInteger(NumberUtils.isCreatable(oldValue + "") ? oldValue + "" : "0");
                        if (newInt.compareTo(oldInt) != 0) {
                            sb.append(showMsg(newVo, newInt, oldInt));
                        }
                    } else if ("java.lang.Boolean".equals(typeName) || Boolean.TYPE == type) {
                        java.lang.Boolean newbool = BooleanUtils.toBoolean(newValue + "") ? true : false;
                        java.lang.Boolean oldbool = BooleanUtils.toBoolean(oldValue + "") ? true : false;
                        if (!newbool.equals(oldbool)) {
                            sb.append(showMsg(newVo, newbool, oldbool));
                        }
                    } else if ("java.lang.Character".equals(typeName) || Character.TYPE == type) {
                        // 预留
                    } else if ("java.lang.Byte".equals(typeName) || Byte.TYPE == type) {
                        // 预留不处理
                    } else if ("java.lang.Short".equals(typeName) || Short.TYPE == type) {
                        // 预留不处理 有需要在处理
                    } else if ("java.lang.Float".equals(typeName) || Float.TYPE == type) {
                        java.lang.Float newFloat =
                            NumberUtils.createFloat(NumberUtils.isCreatable(newValue + "") ? newValue + "" : "0");
                        java.lang.Float oldFloat =
                            NumberUtils.createFloat(NumberUtils.isCreatable(oldValue + "") ? oldValue + "" : "0");
                        if (newFloat.compareTo(oldFloat) != 0) {
                            sb.append(showMsg(newVo, newFloat, oldFloat));
                        }
                    } else if ("java.lang.Double".equals(typeName) || Double.TYPE == type) {
                        java.lang.Double newDouble =
                            NumberUtils.createDouble(NumberUtils.isCreatable(newValue + "") ? newValue + "" : "0");
                        java.lang.Double oldDouble =
                            NumberUtils.createDouble(NumberUtils.isCreatable(oldValue + "") ? oldValue + "" : "0");
                        if (newDouble.compareTo(oldDouble) != 0) {
                            sb.append(showMsg(newVo, newDouble, oldDouble));
                        }
                    } else if ("java.util.Date".equals(typeName)) {
                        DateFormat format = new SimpleDateFormat(
                            StringUtils.isBlank(newVo.getFormat()) ? "yyyy-MM-dd" : newVo.getFormat());
                        java.util.Date newTime = (java.util.Date)newValue;
                        java.util.Date oldTime = (java.util.Date)oldValue;
                        String newTempTimeStr = "";
                        String oldTimeTimeStr = "";
                        if (newTime != null) {
                            newTempTimeStr = format.format(newTime);
                        }
                        if (oldTime != null) {
                            oldTimeTimeStr = format.format(oldTime);
                        }
                        if (!StringUtils.equals(newTempTimeStr, oldTimeTimeStr)) {
                            sb.append(showMsg(newVo, format.format(newTime), format.format(oldTime)));
                        }
                    }
                }
            }
        }
        return sb;
    }

    private static String showMsg(LogValue newVo, Object newLog, Object oldLog) {
        return "[" + newVo.getName() + "]发生变化由原先的:" + oldLog + "改变为:" + newLog + "<br>";
    }

    /**
     * 将要转化的对象进行拆分为Map<String,LogValue> LogValue 保存自定义标签的名称 和 数值等内容
     * 
     * @param entity
     * @return
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     * @throws IntrospectionException
     */
    public static Map<String, LogValue> getValuesToMap(Object entity)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, IntrospectionException {
        Map<String, LogValue> comparMap = new HashMap<String, LogValue>();
        java.lang.reflect.Field[] fields = entity.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            String name = fields[i].getName();
            if (PropertyUtils.isReadable(entity, name) && PropertyUtils.isWriteable(entity, name)) {
                if (fields[i].isAnnotationPresent(Compare.class)) {
                    Compare logVo = fields[i].getAnnotation(Compare.class);
                    LogValue lv = new LogValue(logVo.name(), getProperties(entity, name), logVo.dateFormat());
                    comparMap.put(name, lv);
                }
            }
        }
        return comparMap;
    }

    private static Object getProperties(Object b, String name)
        throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        /*
        PropertyDescriptor p = new PropertyDescriptor(name, b.getClass());
        //通过内省的方法来执行制定字段的get方法
        Method mathGet = p.getReadMethod();
        mathGet.setAccessible(true);
        Object age = mathGet.invoke(b);*/

        BeanInfo beanInfo = Introspector.getBeanInfo(b.getClass());
        PropertyDescriptor[] mathAll = beanInfo.getPropertyDescriptors();
        Object value = null;
        for (PropertyDescriptor pd : mathAll) {
            if (pd.getName().equals(name)) {
                Method mathGet = pd.getReadMethod();
                mathGet.setAccessible(true);
                value = mathGet.invoke(b);
            }
        }

        return value;
    }

    public static Object getObjDefault(Object obj) {
        // 得到类对象
        Class<? extends Object> objCla = obj.getClass();
        Field[] fs = objCla.getDeclaredFields();
        for (int i = 0; i < fs.length; i++) {
            Field f = fs[i];

            // 设置些属性是可以访问的
            boolean isStatic = Modifier.isStatic(f.getModifiers());
            if (isStatic) {
                continue;
            }
            // 设置些属性是可以访问的
            f.setAccessible(true);
            try {
                // 得到此属性的值
                Object val = f.get(obj);
                // 得到此属性的类型
                String type = f.getType().toString();
                if (type.endsWith("String") && val == null) {
                    // 给属性设值
                    f.set(obj, "");
                } else if ((type.endsWith("int") || type.endsWith("Integer") || type.endsWith("double"))
                    && val == null) {
                    f.set(obj, 0);
                } else if ((type.endsWith("long") || type.endsWith("Long")) && val == null) {
                    f.set(obj, 0L);
                } else if (type.endsWith("Date") && val == null) {
                    f.set(obj, Date.valueOf("1970-01-01"));
                } else if (type.endsWith("Timestamp") && val == null) {
                    f.set(obj, Timestamp.valueOf("1970-01-01 00:00:00"));
                } else if (type.endsWith("BigDecimal") && val == null) {
                    f.set(obj, BigDecimal.ZERO);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return obj;
    }
}
